<template>
  <div class="my-table">
    <div
      v-if="sortedData.length"
      class="table-container"
      :style="{ maxHeight: maxHeight }"
      @scroll="handleScroll"
    >
      <table>
        <thead>
          <tr>
            <th v-if="selectable">
              <input
                type="checkbox"
                :checked="isAllSelected"
                @change="toggleSelectAll"
              />
            </th>
            <th
              v-for="col in columns"
              :key="col.prop"
              @click="col.sortable ? handleSort(col) : null"
              style="cursor: pointer"
            >
              {{ col.label }}
              <span v-if="col.sortable">
                <span v-if="sortProp === col.prop && sortOrder === 'asc'"
                  >▲</span
                >
                <span v-else-if="sortProp === col.prop && sortOrder === 'desc'"
                  >▼</span
                >
                <span v-else>⇅</span>
              </span>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr
            v-for="(row, rowIndex) in sortedData"
            :key="row[rowKey] ?? rowIndex"
          >
            <td v-if="selectable">
              <input
                type="checkbox"
                :checked="isSelected(row)"
                @change="toggleSelect(row)"
              />
            </td>
            <td v-for="col in columns" :key="col.prop">
              <slot :name="col.prop" :row="row" :value="row[col.prop]">
                {{ row[col.prop] }}
              </slot>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <div v-else class="empty-box">
      <Empty :size="120"></Empty>
    </div>
  </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue';
import Empty from '@/components/Empty.vue';

const props = defineProps({
  columns: {
    // 列配置,在这里增加sortable属性,可以开启排序
    type: Array,
    required: true,
  },
  data: {
    // 数据
    type: Array,
    required: true,
  },
  selectable: {
    type: Boolean,
    default: false,
  },
  rowKey: {
    type: String,
    default: 'id',
  },
  selected: {
    type: Array,
    default: () => [],
  },
  maxHeight: {
    type: String,
    default: '400px',
  },
});

const emit = defineEmits(['update:selected', 'scroll']);

const sortProp = ref('');
const sortOrder = ref(''); // 'asc' | 'desc' | ''

function handleSort(col) {
  if (sortProp.value !== col.prop) {
    sortProp.value = col.prop;
    sortOrder.value = 'asc';
  } else if (sortOrder.value === 'asc') {
    sortOrder.value = 'desc';
  } else if (sortOrder.value === 'desc') {
    sortProp.value = '';
    sortOrder.value = '';
  } else {
    sortOrder.value = 'asc';
  }
}

const sortedData = computed(() => {
  if (!sortProp.value || !sortOrder.value) return props.data;
  return [...props.data].sort((a, b) => {
    const v1 = a[sortProp.value];
    const v2 = b[sortProp.value];
    if (v1 === v2) return 0;
    if (sortOrder.value === 'asc') return v1 > v2 ? 1 : -1;
    return v1 < v2 ? 1 : -1;
  });
});

const selectedRows = ref([...props.selected]);

watch(
  () => props.selected,
  (val) => {
    selectedRows.value = [...val];
  }
);

function isSelected(row) {
  return selectedRows.value.some((r) => r[props.rowKey] === row[props.rowKey]);
}

function toggleSelect(row) {
  const idx = selectedRows.value.findIndex(
    (r) => r[props.rowKey] === row[props.rowKey]
  );
  if (idx > -1) {
    selectedRows.value.splice(idx, 1);
  } else {
    selectedRows.value.push(row);
  }
  emit('update:selected', selectedRows.value);
}

const isAllSelected = computed(() => {
  if (!props.data.length) return false;
  return props.data.every((row) =>
    selectedRows.value.some((r) => r[props.rowKey] === row[props.rowKey])
  );
});

function toggleSelectAll() {
  if (isAllSelected.value) {
    selectedRows.value = [];
  } else {
    selectedRows.value = [...props.data];
  }
  emit('update:selected', selectedRows.value);
}

function handleScroll(event) {
  emit('scroll', event);
}
</script>

<style scoped lang="scss">
.my-table {
  font-size: 22px;
  border-radius: 6px;
  overflow: hidden;

  .table-container {
    // max-height: 400px; // 设置最大高度，可以根据需要调整
    overflow-y: auto; // 垂直滚动
    border-radius: 6px;
    border: 1px solid #ebeef5;
    border-top: 0;
  }

  .empty-box {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%; // 确保空状态占满整个表格区域
  }

  table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    border-radius: 6px;
  }

  thead {
    position: sticky;
    top: -1px;
    z-index: 2;
    background: #f0f2f6;
  }

  thead tr {
    background: #f0f2f6;
  }

  th,
  td {
    border: 1px solid #ebeef5;
    padding: 10px 12px;
    text-align: left;
    background-clip: padding-box;
    color: #666;
  }

  // 四个角加圆角
  thead tr:first-child th:first-child {
    border-top-left-radius: 6px;
  }
  thead tr:first-child th:last-child {
    border-top-right-radius: 6px;
  }
  tbody tr:last-child td:first-child {
    border-bottom-left-radius: 6px;
  }
  tbody tr:last-child td:last-child {
    border-bottom-right-radius: 6px;
  }

  th {
    color: #333;
    background: #f0f2f6;
    font-weight: bold;
    user-select: none;
  }

  th[style*='cursor: pointer'] {
    transition: background 0.2s;
  }
}
</style>
